
Type CalMorphTargetMixer

	Field m_model:CalModel
	Field m_vectorCurrentWeight:Float[]
	Field m_vectorEndWeight:Float[]
	Field m_vectorDuration:Float[]
	Field mPlayTime:Float
	Field mDuration:Float
	Field mPlayedAnimatedMorphID:Int
	Method New()
	
		m_model = Null
		m_vectorCurrentWeight = New Float[0]
		m_vectorEndWeight = New Float[0]
		m_vectorDuration = New Float[0]		
	
	End Method
	
	Function FromModel:CalMorphTargetMixer(model:CalModel)
		cmt:CalMorphTargetMixer = New CalMorphTargetMixer
		cmt.m_model = model
		Local morphAnimationCount:Int = model.getCoreModel().getCoreMorphAnimationCount()
		cmt.m_vectorCurrentWeight = New Float[morphAnimationCount]
		cmt.m_vectorEndWeight = New Float[morphAnimationCount]
		cmt.m_vectorDuration = New Float[morphAnimationCount]			
		Return cmt
	End Function


	Method blend:Byte(id:Int, weight:Float, Delay:Float)
	
		If id < 0 Or id >= m_vectorCurrentWeight.length Then
			DebugLog "Invalid Morph ID"
			Return False
		EndIf
		mPlayedAnimatedMorphID = id
		m_vectorEndWeight[id] = weight
		m_vectorDuration[id] = Delay
		'mDuration = Delay
		Return True		
	
	End Method
	
	
	Method clear:Byte(id:Int, Delay:Float)
		If id < 0 Or id >= m_vectorCurrentWeight.length Then
			DebugLog "Invalid Morph ID"
			Return False
		EndIf
	
		m_vectorEndWeight[id] = 0
		m_vectorDuration[id] = Delay
		Return True		
	End Method
	
	Method getCurrentWeight:Float(id:Int)
		If id < 0 Or id >= m_vectorCurrentWeight.length Then
			DebugLog "Invalid Morph ID"
			Return False
		EndIf
		
		Return m_vectorCurrentWeight[id]	
	End Method
	
	Method getCurrentWeightBase:Float()
	
		Local currentWeight:Float = 1
		For Local i:Int = 0 To m_vectorCurrentWeight.length-1
			currentWeight = currentWeight-m_vectorCurrentWeight[i]
		Next
	
		Return currentWeight
		
	End Method
	
	Method getMorphTargetCount:Int()
		Return m_vectorCurrentWeight.length
	End Method

	Rem
	Method updateold(deltaTime:Float)
		For Local i:Int = 0 To m_vectorCurrentWeight.length-1
			Local currentWeight:Float = m_vectorCurrentWeight[i]
			Local endWeight:Float = m_vectorEndWeight[i]
			Local duration:Float = m_vectorDuration[i]
	
			If deltaTime >= duration Then
				m_vectorCurrentWeight[i] = endWeight
				m_vectorDuration[i] = 0
			Else
				m_vectorCurrentWeight[i] = m_vectorCurrentWeight[i]+(endWeight - currentWeight) * deltaTime / duration
				m_vectorDuration[i] = m_vectorDuration[i]-deltaTime
			EndIf
		Next
	
		For Local morphAnimationID:Int = 0 To m_vectorCurrentWeight.length-1
			Local coreMorphAnimation:CalCoreAnimatedMorph = m_model.getCoreModel().getCoreAnimatedMorph(morphAnimationID)
	
			Local vectorCoreMeshID:Int[] = coreMorphAnimation.getVectorCoreMeshID()
			Local vectorMorphTargetID:Int[] = coreMorphAnimation.getVectorMorphTargetID()
	
			For i = 0 To vectorCoreMeshID.length-1
				Local vectorSubmesh:CalSubmesh[] = m_model.getMesh(vectorCoreMeshID[i]).getVectorSubmesh()
	
				Local submeshCount:Int = vectorSubmesh.length
				For Local submeshId:Int = 0 To submeshCount-1
					vectorSubmesh[submeshId].setMorphTargetWeight(vectorMorphTargetID[i],  m_vectorCurrentWeight[morphAnimationID])
				Next
			Next
		Next	
	End Method
	End Rem


	
	Method update(deltaTime:Float)
		'DebugLog "Mixing Morph"
		If mPlayedAnimatedMorphID < 0 Or mPlayedAnimatedMorphID >= m_vectorEndWeight.Length Then
			'DebugLog "Bad morph ID"
			Return
		EndIf
		If m_vectorEndWeight[mPlayedAnimatedMorphID] = 0 Then Return
		mPlayTime = mPlayTime + deltaTime
		
		Local morph:CalCoreAnimatedMorph = m_model.getCoreModel().getCoreAnimatedMorph(mPlayedAnimatedMorphID)
		
		If morph = Null
			DebugLog "Morph was null"
			Return
		Else
			If mPlayTime > morph.m_duration Then mPlayTime = 0
		EndIf
		
		SetTrackWeights(morph, mPlayTime)
	End Method
	
	Method SetTrackWeights(morph:CalCoreAnimatedMorph, elapsedTime:Float)
	
		Local tracks:CalCoreMorphTrack[] = morph.getListCoreTrack()
		
		For Local itr:Int = 0 To tracks.length-1
			
			Local track:CalCoreMorphTrack = tracks[itr]
			Local keyFrames:CalCoreMorphKeyframe[] = track.getVectorCoreMorphKeyframes() 
			
			Local trackWeight:Float = 0.0
			
			If keyFrames.length = 0 Then
				DebugLog "No Keyframes"
				trackWeight = 0.0
			Else
				trackWeight = CalcKeyframeWeight(keyFrames, elapsedTime)
				
			EndIf
			ApplyWeightToMorphMesh(track.getMorphName(), trackWeight)
		Next
	
	End Method


	Method CalcKeyframeWeight:Float(keyFrames:CalCoreMorphKeyframe[],elapsedTime:Float)
	
		'std::vector<CalCoreMorphKeyframe>::const_iterator keyframeItr;
		Local key:Int
		'//find the first key frame that has a time greater than the elapsed time
		For Local i:Int = 0 To keyFrames.length-1
			key = i
			If keyFrames[i].getTime() > elapsedTime Then
				
				Exit
			EndIf
		
		Next
		'If the key frame is the first, Or there aren't any key frames left to play
		'Then set the weight To zero
		If key = keyFrames.length-1 Or key = 0 Then
		
			Return 0.0
			
		EndIf
		
		Local endTime:Float = keyFrames[key].getTime()
		Local endWeight:Float = keyFrames[key].getWeight()
		
		'get the previous key frame
		key = key - 1
		Local startTime:Float = keyFrames[key].getTime()
		Local startWeight:Float = keyFrames[key].getWeight()
		'Return endWeight*((Delta.delta/30)*elapsedTime)
		Return MapRangeValue(elapsedTime, startTime, endTime, startWeight, endWeight)
	End Method
	
	Method Lerp:Float(x:Float,y:Float,t:Float)
	
   		Return x + t * (y - x)

	End Method

	Method MapRangeValue:Float(sX:Float,xMin:Float,xMax:Float, yMin:Float,yMax:Float)
	 'DebugLog "map vals"
		Return Lerp( yMin, yMax, (Delta.delta/Delta.targetfps))'CalcNormal(sX,xMin,xMax))
		 
	End Method

	Method CalcNormal:Float(sX:Float,sMin:Float,sMax:Float)
		'T delta( sMax - sMin );
		'DebugLog "Normal: "+sX+" "+sMax
		Return (sX-sMin) / (Delta.delta/Delta.targetfps)
		
	End Method

	Method ApplyWeightToMorphMesh(morphMeshName:String,trackWeight:Float)
	
		Local meshVec:CalMesh[] = m_model.getVectorMesh()
		For Local i:Int = 0 To meshVec.length-1
			Local subMeshVec:CalSubmesh[] = meshVec[i].getVectorSubmesh()
			For Local ii:Int = 0 To subMeshVec.length-1
				'setMorphTargetWeight(morphMeshName, trackWeight)
				'DebugLog "Set: "+morphMeshName
				subMeshVec[ii].setMorphTargetWeightbyName(morphMeshName, trackWeight)
			Next
		Next
	
	End Method
	
End Type
